package ldh.im.fxgui.rpc.router;

import ldh.im.dto.base.OkResp;
import ldh.im.dto.business.file.FileUploadSuccessReq;
import ldh.im.dto.business.item.MessageListItem;
import ldh.im.dto.business.message.MessageObject;
import ldh.im.dto.business.message.MessageReadReq;
import ldh.im.dto.business.message.MessageWithdrawReq;
import ldh.im.fxbase.dao.ImMessageDao;
import ldh.im.fxbase.data.pojo.ImMessage;
import ldh.im.fxbase.data.pojo.status.ImMessageFileStatus;
import ldh.im.fxbase.util.FxThreadUtil;
import ldh.im.fxbase.util.RpcUtil;
import ldh.im.fxgui.service.DefaultFileProgressListener;
import ldh.im.fxgui.service.MessageReadService;
import ldh.im.fxgui.service.MessageReceiveService;
import ldh.im.fxbase.util.BeanFactory;
import ldh.im.fxgui.util.UiUtil;
import ldh.rpc.util.JsonUtil;
import ldh.rpc.Rpc;
import ldh.rpc.RpcMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.time.Duration;
import java.time.LocalDateTime;
import java.util.Arrays;

/**
 * 服务器给客户端发送的消息
 *  1, 转发消息
 *  2, 已读事件
 *  3, 文件上传成功事件
 */
@Rpc
public class MessageConsumerRouter {

    private static final Logger LOGGER = LoggerFactory.getLogger(MessageConsumerRouter.class);

    private MessageReceiveService messageReceiveService = BeanFactory.getInstance().getBean(MessageReceiveService.class);
    private ImMessageDao messageDao = BeanFactory.getInstance().getBean(ImMessageDao.class);

    /**
     * 接受服务器端的消息
     * @param messageObject
     * @return
     * @throws Exception
     */
    @RpcMapper(path="serverMessage", asynHandle = true)
    public OkResp receiveMessage(MessageObject messageObject) throws Exception {
        long time = Duration.between(messageObject.getCreateDateTime(), LocalDateTime.now()).toMillis();
        LOGGER.info("收到服务端转发消息，receive message time: {}, data: {}", time, JsonUtil.toJson(messageObject));
        String userId = UiUtil.getLoginImUser().getUserId();
        messageReceiveService.handleReceiveMessage(userId, messageObject);
        return new OkResp();
    }

    /**
     * 接受服务器端的批量消息
     * @param messageListItem
     * @return
     * @throws Exception
     */
    @RpcMapper(path="serverMessages", asynHandle = true)
    public OkResp receiveMessages(MessageListItem messageListItem) throws Exception {
        LOGGER.info("收到服务端消息, receive message list {}", JsonUtil.toJson(messageListItem));
        for (MessageObject messageObject : messageListItem.getMessageObjectList()) {
            receiveMessage(messageObject);
        }
        return new OkResp();
    }

    /**
     * 接受服务端的已读消息
     * @param messageReadReq
     * @return
     * @throws Exception
     */
    @RpcMapper(path="serverReadMessage", asynHandle = true)
    public OkResp receiveReadMessage(MessageReadReq messageReadReq) throws Exception {
        LOGGER.info("收到服务端已读事件, receive message read {}", JsonUtil.toJson(messageReadReq));
        String userId = UiUtil.getLoginImUser().getUserId();
        messageReceiveService.handleReadMessages(userId, messageReadReq.getMessageIds());
        return new OkResp();
    }

    /**
     * 接受服务端的消息回撤
     * @param messageWithdrawReq
     * @return
     * @throws Exception
     */
    @RpcMapper(path="serverWithdrawMessage", asynHandle = true)
    public OkResp receiveWithdrawMessage(MessageWithdrawReq messageWithdrawReq) throws Exception {
        LOGGER.info("收到服务端撤回事件, receive withdraw message {}", JsonUtil.toJson(messageWithdrawReq));
        String userId = UiUtil.getLoginImUser().getUserId();
        messageReceiveService.handleWithdrawMessages(userId, messageWithdrawReq.getMessageIds());
        return new OkResp();
    }

    /**
     * 文件上传成功后，服务器回执消息
     * @param fileUploadSuccessReq
     * @return
     * @throws Exception
     */
    @RpcMapper(path="serverRedirectFileUploadSuccess", asynHandle = true)
    public OkResp receiveFileUploadSuccessMessage(FileUploadSuccessReq fileUploadSuccessReq) throws Exception {
        LOGGER.info("收到服务端文件上传成功事件, receive file upload success {}", JsonUtil.toJson(fileUploadSuccessReq));
        String messageId = fileUploadSuccessReq.getMessageId();
        String userId = UiUtil.getLoginImUser().getUserId();
        ImMessage imMessage = messageDao.getMessageByServerId(userId, messageId);
        imMessage.setFileStatus(ImMessageFileStatus.none);
        messageDao.changeMessageFileStatus(imMessage.getId(), ImMessageFileStatus.none);

        // 开始下载附件
        imMessage.setFileStatus(ImMessageFileStatus.downloading);
        FxThreadUtil.runLater(()-> {
            UiUtil.uiUpdateMessage(imMessage);
        });
        RpcUtil.getImService().downloadFile(imMessage, new DefaultFileProgressListener(), this::uiUpdateMessage);
        return new OkResp();
    }

    private void uiUpdateMessage(ImMessage message) {
        UiUtil.uiUpdateMessage(message);
        MessageReadService.getInstance().asyHandleReadMessage(message.getSessionId(), message.getCurrentUserId(), Arrays.asList(message));
    }
}
